<!DOCTYPE html>
<html lang="en">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Porting to GCC 9</title>
<link rel="stylesheet" type="text/css" href="https://gcc.gnu.org/gcc.css" />
</head>

<body>
<h1>Porting to GCC 9</h1>

<p>
The GCC 9 release series differs from previous GCC releases in
<a href="changes.html">a number of ways</a>. Some of these are a result
of bug fixing, and some old behaviors have been intentionally changed
to support new standards, or relaxed in standards-conforming ways to
facilitate compilation or run-time performance.
</p>

<p>
Some of these changes are user visible and can cause grief when
porting to GCC 9. This document is an effort to identify common issues
and provide solutions. Let us know if you have suggestions for improvements!
</p>


<!--
<h2 id="cpp">Preprocessor issues</h2>
-->

<h2 id="c">C language issues</h2>

<h3 id="complit">Block scope compound literal's lifetime</h3>

<p>
  The C standard says that compound literals which occur inside of the body
  of a function have automatic storage duration associated with the
  enclosing block.  Older GCC releases were putting such compound literals
  into the scope of the whole function, so their lifetime actually ended
  at the end of containing function.  This has been fixed in GCC 9.
  Code that relied on this extended lifetime needs to be fixed, move the
  compound literals to whatever scope they need to accessible in.
</p>
  <pre><code>
      struct S { int a, b; };
      int foo(void) {
        // The following line no longer compiles
        struct S *p = &amp;({ (struct S) { 1, 2 }; });
        struct S *q;
        {
          q = &(struct S) { 3, 4 };
        }
        // This is invalid use after lifetime of the compound literal
        // ended.
        return q-&gt;b;
      }
  </code></pre>

<h3 id="ompdatasharing">OpenMP data sharing</h3>

<p>
  GCC releases before 9 were implementing an OpenMP 3.1 data sharing rule
  that <code>const</code> qualified variables without <code>mutable</code>
  member are predetermined shared, but as an exception may be specified
  in the <code>firstprivate</code> clause.  OpenMP 4.0 dropped this rule,
  but in the hope that the incompatible change will be reverted GCC kept
  implementing the previous behavior.  Now that for OpenMP 5.0 it has been
  confirmed this is not going to change, GCC 9 started implementing the
  OpenMP 4.0 and later behavior.  When not using <code>default</code>
  clause or when using <code>default(shared)</code>, this makes no
  difference, but if using <code>default(none)</code>, previously the
  choice was not specify the <code>const</code> qualified variables
  on the construct at all, or specify in <code>firstprivate</code> clause.
  In GCC 9 as well as for OpenMP 4.0 compliance, those variables need
  to be specified on constructs in which they are used, either in
  <code>shared</code> or in <code>firstprivate</code> clause.  Specifying
  them in <code>firstprivate</code> clause is one way to achieve
  compatibility with both older GCC versions and GCC 9, another option
  is to drop the <code>default(none)</code> clause.  In C++,
  <code>const</code> variables with constant initializers which are not
  odr-used in the region, but replaced with their constant initializer
  are not considered to be referenced in the region for
  <code>default(none)</code> purposes.
</p>
  <pre><code>
      int get (void);
      void use (int);
      void foo (void) {
        const int a = get ();
        const int b = 1;
        #pragma omp parallel for default(none)
        for (int i = 0; i &lt; a; i += b)
          ;
        // The above used to compile with GCC 8 and older, but will
        // not anymore with GCC 9.  firstprivate(a, b) clause needs
        // to be added for C, for C++ it could be just firstprivate(a)
        // to make it compatible with all GCC releases.
      }
      const int huge_array[1024] = { ... };
      void bar (void) {
        #pragma omp parallel for default(none)
        for (int i = 0; i &lt; 1024; i++)
          use (huge_array[i]);
        // Similarly, this used to compile with GCC 8 and older and
        // will not anymore.  Adding firstprivate(huge_array) is
        // probably undesirable here, so, either
        // default(none) shared(huge_array) should be used and it will
        // only support GCC 9 and later, or default(none) should be
        // removed and then it will be compatible with all GCC releases
        // and huge_array will be shared.
      }
  </code></pre>

<h2 id="cxx">C++ language issues</h2>

<h3>
  <code>operator new(size_t, nothrow_t)</code> calls
  <code>operator new(size_t)</code>
</h3>

<p>
GCC 9 implements the requirement introduced in the C++ 2011 standard that
the <code>nothrow</code> version of <code>operator new</code> calls the
ordinary, throwing version of <code>operator new</code> (and catches any
exception and instead returns a null pointer). 
This was changed by <a href="https://wg21.link/lwg206">DR 206</a> to ensure
that the various forms of <code>operator new</code> do not become decoupled
if a user only replaces the ordinary <code>operator new</code>.
</p>

<p>
Code that only replaces one version of <code>operator new</code> and expects
the other versions to be unaffected might change behaviour when using GCC 9.
</p>

<p>
If your program uses a replacement <code>operator new(size_t, nothrow_t)</code>
then it must also replace <code>operator new(size_t)</code> and
<code>operator delete(void*)</code>, and ensure memory obtained from the
<code>nothrow</code> version of <code>new</code> can be freed by the ordinary
version of <code>operator delete</code>.
</p>

<p>
The simplest solution is to only replace the ordinary
<code>operator new(size_t)</code> and
<code>operator delete(void*)</code> and
<code>operator delete(void*, size_t)</code>
functions, and the replaced versions will be used by all of
<code>operator new(size_t, nothrow_t)</code>,
<code>operator new[](size_t)</code> and
<code>operator new[](size_t, nothrow_t)</code>
and the corresponding <code>operator delete</code> functions.
To support types with extended alignment you may also need to replace
<code>operator new(size_t, align_val_t)</code> and
<code>operator delete(void*, align_val_t)</code> and
<code>operator delete(void*, align_val_t)</code>
(which will then be used by the <code>nothrow</code> and array forms for
extended alignments).
</p>

<!--
<h2 id="fortran">Fortran language issues</h2>
-->
 
<!--
<h2 id="links">Links</h2>
-->

</body>
</html>
